ListView.builder in Flutter – Detailed Notes
ListView.builder is a Flutter widget constructor used to create scrollable lists dynamically. It is especially useful when an application needs to display a large or dynamically changing number of items. Unlike a regular ListView with an explicit children list, ListView.builder creates list children on demand as they become visible. This makes it suitable for large or potentially infinite lists. :contentReference[oaicite:0]{index=0}
1. What is ListView.builder?
ListView.builder creates a scrollable, linear collection of widgets using an itemBuilder callback. The callback receives the current index and returns the widget that should appear at that position.
It is commonly used for:
- Student lists
- Employee lists
- Product lists
- Contact lists
- Chat messages
- Notifications
- News feeds
- Shopping cart items
- Search results
- Data received from APIs
2. Why Use ListView.builder?
When a list contains a large number of items, creating every widget at once is unnecessary. ListView.builder builds children lazily, meaning Flutter creates the children that are needed for the visible portion of the list rather than constructing the entire collection at once. :contentReference[oaicite:1]{index=1}
- Efficient for large lists.
- Suitable for dynamic data.
- Supports potentially infinite lists.
- Creates children on demand.
- Works with local and remote data.
- Supports vertical and horizontal scrolling.
- Can be combined with user interaction and navigation.
3. Basic Syntax
ListView.builder(
itemCount: items.length,
itemBuilder: (context, index) {
return Widget();
},
)
The two most important properties are itemCount and itemBuilder.
4. Understanding itemCount
itemCount specifies the number of items that the list should represent.
ListView.builder(
itemCount: students.length,
itemBuilder: (context, index) {
return Text(students[index]);
},
)
If students contains five elements, itemCount will be five and the builder receives indexes from 0 through 4. Providing a non-null itemCount also helps Flutter estimate the maximum scroll extent more accurately. :contentReference[oaicite:2]{index=2}
5. Understanding itemBuilder
itemBuilder is a callback that creates the widget for each list position.
itemBuilder: (context, index) {
return ListTile(
title: Text('Item ${index + 1}'),
);
}
The index tells you which item is currently being built.
6. Simple ListView.builder Example
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
appBar: AppBar(
title: const Text('ListView.builder'),
),
body: ListView.builder(
itemCount: 20,
itemBuilder: (context, index) {
return ListTile(
leading: const Icon(Icons.list),
title: Text('Item ${index + 1}'),
);
},
),
),
);
}
}
7. How ListView.builder Works
- Create or receive a data source.
- Pass the number of items to
itemCount.
- Provide an
itemBuilder callback.
- Flutter provides the current index to the callback.
- The callback creates the corresponding widget.
- As the user scrolls, additional visible children are built as required.
ListView.builder(
itemCount: students.length,
itemBuilder: (context, index) {
final student = students[index];
return ListTile(
title: Text(student),
);
},
)
8. ListView.builder with a List of Strings
final List students = [
'Rahul',
'Priya',
'Amit',
'Neha',
'Pooja',
];
ListView.builder(
itemCount: students.length,
itemBuilder: (context, index) {
return ListTile(
leading: const Icon(Icons.person),
title: Text(students[index]),
);
},
)
9. ListView.builder with List of Maps
final List
10. ListView.builder with Model Classes
For larger Flutter applications, model classes make structured data easier to manage.
class Product {
final String name;
final double price;
final String category;
Product({
required this.name,
required this.price,
required this.category,
});
}
Create the data:
final List products = [
Product(
name: 'Laptop',
price: 55000,
category: 'Electronics',
),
Product(
name: 'Phone',
price: 25000,
category: 'Electronics',
),
Product(
name: 'Headphones',
price: 3000,
category: 'Accessories',
),
];
Display it using ListView.builder:
ListView.builder(
itemCount: products.length,
itemBuilder: (context, index) {
final product = products[index];
return Card(
child: ListTile(
leading: const Icon(Icons.shopping_bag),
title: Text(product.name),
subtitle: Text(product.category),
trailing: Text(
'₹${product.price.toStringAsFixed(0)}',
),
),
);
},
)
11. ListView.builder with Cards
ListView.builder(
padding: const EdgeInsets.all(12),
itemCount: products.length,
itemBuilder: (context, index) {
final product = products[index];
return Card(
margin: const EdgeInsets.only(bottom: 12),
elevation: 3,
child: ListTile(
leading: const CircleAvatar(
child: Icon(Icons.shopping_bag),
),
title: Text(product.name),
subtitle: Text(product.category),
trailing: Text(
'₹${product.price.toStringAsFixed(0)}',
),
),
);
},
)
12. Horizontal ListView.builder
By default, ListView.builder scrolls vertically. Set scrollDirection: Axis.horizontal to create a horizontal list.
final List categories = [
'Electronics',
'Fashion',
'Books',
'Sports',
'Shoes',
];
ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: categories.length,
itemBuilder: (context, index) {
return Container(
width: 140,
margin: const EdgeInsets.all(8),
child: Card(
child: Center(
child: Text(categories[index]),
),
),
);
},
)
13. Adding Padding
ListView.builder(
padding: const EdgeInsets.all(16),
itemCount: 10,
itemBuilder: (context, index) {
return Card(
margin: const EdgeInsets.only(bottom: 10),
child: ListTile(
title: Text('Item ${index + 1}'),
),
);
},
)
14. Adding Separators
If every item needs a separator, ListView.separated can be used instead of manually adding separator widgets. It provides an itemBuilder for items and a separatorBuilder for separators. :contentReference[oaicite:3]{index=3}
ListView.separated(
itemCount: students.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(students[index]),
);
},
separatorBuilder: (context, index) {
return const Divider();
},
)
15. onTap with ListView.builder
List items can respond to user interaction using onTap.
ListView.builder(
itemCount: students.length,
itemBuilder: (context, index) {
return ListTile(
leading: const Icon(Icons.person),
title: Text(students[index]),
onTap: () {
print('Selected: ${students[index]}');
},
);
},
)
16. Navigating to a Detail Screen
A common pattern is to pass the selected list item to another screen.
ListView.builder(
itemCount: products.length,
itemBuilder: (context, index) {
final product = products[index];
return ListTile(
title: Text(product.name),
subtitle: Text('₹${product.price}'),
trailing: const Icon(Icons.arrow_forward_ios),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) {
return ProductDetails(product: product);
},
),
);
},
);
},
)
17. Detail Screen Example
class ProductDetails extends StatelessWidget {
final Product product;
const ProductDetails({
super.key,
required this.product,
});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(product.name),
),
body: Padding(
padding: const EdgeInsets.all(20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
product.name,
style: const TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 10),
Text('Category: ${product.category}'),
const SizedBox(height: 10),
Text('Price: ₹${product.price}'),
],
),
),
);
}
}
18. Dynamic List with Add Item
ListView.builder works well with setState() when list data changes.
class StudentPage extends StatefulWidget {
const StudentPage({super.key});
@override
State createState() => _StudentPageState();
}
class _StudentPageState extends State {
final List students = [
'Rahul',
'Priya',
'Amit',
];
void addStudent() {
setState(() {
students.add(
'Student ${students.length + 1}',
);
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Students'),
),
body: ListView.builder(
itemCount: students.length,
itemBuilder: (context, index) {
return ListTile(
leading: const Icon(Icons.person),
title: Text(students[index]),
);
},
),
floatingActionButton: FloatingActionButton(
onPressed: addStudent,
child: const Icon(Icons.add),
),
);
}
}
19. Removing Items
void removeStudent(int index) {
setState(() {
students.removeAt(index);
});
}
Use the function with an icon button:
ListView.builder(
itemCount: students.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(students[index]),
trailing: IconButton(
icon: const Icon(Icons.delete),
onPressed: () {
removeStudent(index);
},
),
);
},
)
20. Swipe to Delete
The Dismissible widget can be combined with ListView.builder to provide swipe-to-delete functionality.
ListView.builder(
itemCount: students.length,
itemBuilder: (context, index) {
return Dismissible(
key: ValueKey(students[index]),
onDismissed: (direction) {
setState(() {
students.removeAt(index);
});
},
background: Container(
color: Colors.red,
alignment: Alignment.centerLeft,
padding: const EdgeInsets.only(left: 20),
child: const Icon(Icons.delete),
),
child: ListTile(
title: Text(students[index]),
),
);
},
)
21. Checkbox List with ListView.builder
final List tasks = [
'Learn Dart',
'Learn Flutter',
'Build a Flutter project',
'Practice ListView.builder',
];
final List completed = [
false,
false,
false,
false,
];
ListView.builder(
itemCount: tasks.length,
itemBuilder: (context, index) {
return CheckboxListTile(
title: Text(tasks[index]),
value: completed[index],
onChanged: (value) {
setState(() {
completed[index] = value ?? false;
});
},
);
},
)
22. ListView.builder with Images
ListView.builder(
itemCount: 10,
itemBuilder: (context, index) {
return ListTile(
leading: CircleAvatar(
backgroundImage: NetworkImage(
'https://example.com/image.jpg',
),
),
title: Text('User ${index + 1}'),
subtitle: const Text('Flutter Developer'),
);
},
)
23. reverse Property
The reverse property reverses the scroll direction. It can be useful for chat-style interfaces.
ListView.builder(
reverse: true,
itemCount: messages.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(messages[index]),
);
},
)
24. Horizontal Product Categories
class CategoryList extends StatelessWidget {
const CategoryList({super.key});
final List categories = const [
'All',
'Electronics',
'Fashion',
'Books',
'Sports',
];
@override
Widget build(BuildContext context) {
return SizedBox(
height: 60,
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: categories.length,
itemBuilder: (context, index) {
return Padding(
padding: const EdgeInsets.symmetric(
horizontal: 6,
),
child: Chip(
label: Text(categories[index]),
),
);
},
),
);
}
}
25. ScrollController
ScrollController allows an application to control and observe the scroll position.
final ScrollController controller = ScrollController();
ListView.builder(
controller: controller,
itemCount: 100,
itemBuilder: (context, index) {
return ListTile(
title: Text('Item ${index + 1}'),
);
},
)
Scrolling to the Top
controller.animateTo(
0,
duration: const Duration(milliseconds: 500),
curve: Curves.easeInOut,
);
Disposing the Controller
@override
void dispose() {
controller.dispose();
super.dispose();
}
26. shrinkWrap
shrinkWrap allows the scrollable to size itself based on its contents along the scrolling direction. It can be useful when a ListView needs to exist inside another layout that imposes a different sizing requirement.
Column(
children: [
const Text('Students'),
ListView.builder(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemCount: students.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(students[index]),
);
},
),
],
)
Do not use shrinkWrap: true unnecessarily because content-based sizing can require additional layout work.
27. physics Property
The physics property controls how the list responds to scrolling gestures.
ListView.builder(
physics: const BouncingScrollPhysics(),
itemCount: 30,
itemBuilder: (context, index) {
return ListTile(
title: Text('Item ${index + 1}'),
);
},
)
Scrolling can also be disabled:
ListView.builder(
physics: const NeverScrollableScrollPhysics(),
itemCount: 10,
itemBuilder: (context, index) {
return ListTile(
title: Text('Item ${index + 1}'),
);
},
)
28. itemExtent
If every item has a known fixed extent in the scrolling direction, itemExtent can be specified. Knowing the child extent can allow Flutter's scrolling machinery to perform less work. :contentReference[oaicite:4]{index=4}
ListView.builder(
itemCount: 100,
itemExtent: 60,
itemBuilder: (context, index) {
return ListTile(
title: Text('Item ${index + 1}'),
);
},
)
29. prototypeItem
prototypeItem can be used when list children have the same extent as a representative widget.
ListView.builder(
itemCount: 100,
prototypeItem: const ListTile(
title: Text('Prototype'),
),
itemBuilder: (context, index) {
return ListTile(
title: Text('Item ${index + 1}'),
);
},
)
Flutter documents prototypeItem, itemExtent, and itemExtentBuilder as ways to provide information about child extent. Only one of these extent mechanisms should be supplied for a given ListView.builder. :contentReference[oaicite:5]{index=5}
30. itemExtentBuilder
itemExtentBuilder can be useful when list items have different extents that can be calculated from the index.
ListView.builder(
itemCount: 20,
itemExtentBuilder: (index, dimensions) {
return index.isEven ? 60 : 90;
},
itemBuilder: (context, index) {
return ListTile(
title: Text('Item ${index + 1}'),
);
},
)
31. Large Lists
ListView.builder is particularly useful for large lists. Flutter's official long-list recipe demonstrates generating 10,000 items and displaying them with ListView.builder. :contentReference[oaicite:6]{index=6}
final List items = List.generate(
10000,
(index) => 'Item $index',
);
ListView.builder(
itemCount: items.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(items[index]),
);
},
)
32. API Data with ListView.builder
In real-world applications, list data frequently comes from an API or database. After retrieving and parsing the data, ListView.builder can convert each data object into a Flutter widget.
class User {
final String name;
final String email;
User({
required this.name,
required this.email,
});
}
final List users = [
User(
name: 'Rahul Sharma',
email: '[email protected]',
),
User(
name: 'Priya Singh',
email: '[email protected]',
),
];
ListView.builder(
itemCount: users.length,
itemBuilder: (context, index) {
final user = users[index];
return ListTile(
leading: const CircleAvatar(
child: Icon(Icons.person),
),
title: Text(user.name),
subtitle: Text(user.email),
);
},
)
33. Loading State
When list data is being loaded from a remote source, the application can display a loading indicator before building the list.
if (isLoading) {
return const Center(
child: CircularProgressIndicator(),
);
}
return ListView.builder(
itemCount: users.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(users[index].name),
);
},
);
34. Empty State
If there are no items, it is better to display a meaningful empty state.
if (users.isEmpty) {
return const Center(
child: Text('No users found'),
);
}
return ListView.builder(
itemCount: users.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(users[index].name),
);
},
);
Flutter's ListView documentation recommends conditionally replacing the list with an empty-state widget when there are no items. :contentReference[oaicite:7]{index=7}
35. Error State
if (hasError) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text('Something went wrong'),
const SizedBox(height: 10),
ElevatedButton(
onPressed: loadUsers,
child: const Text('Retry'),
),
],
),
);
}
36. ListView.builder with FutureBuilder
A common Flutter pattern is to retrieve asynchronous data using FutureBuilder and display the resulting collection with ListView.builder.
Future> fetchStudents() async {
await Future.delayed(
const Duration(seconds: 1),
);
return [
'Rahul',
'Priya',
'Amit',
'Neha',
];
}
FutureBuilder>(
future: fetchStudents(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const Center(
child: CircularProgressIndicator(),
);
}
if (snapshot.hasError) {
return Center(
child: Text('Error: ${snapshot.error}'),
);
}
final students = snapshot.data ?? [];
if (students.isEmpty) {
return const Center(
child: Text('No students found'),
);
}
return ListView.builder(
itemCount: students.length,
itemBuilder: (context, index) {
return ListTile(
leading: const Icon(Icons.person),
title: Text(students[index]),
);
},
);
},
)
37. Avoid Calling API Directly Inside itemBuilder
The itemBuilder should normally build a widget from already available data. Avoid starting a network request for every list item from inside itemBuilder. Fetch and prepare the data separately, then use the builder to render it.
ListView.builder(
itemCount: users.length,
itemBuilder: (context, index) {
final user = users[index];
return ListTile(
title: Text(user.name),
subtitle: Text(user.email),
);
},
)
38. ListView.builder with Search Results
final List allStudents = [
'Rahul',
'Priya',
'Amit',
'Neha',
'Pooja',
];
String searchText = '';
List get filteredStudents {
return allStudents
.where(
(student) => student
.toLowerCase()
.contains(searchText.toLowerCase()),
)
.toList();
}
ListView.builder(
itemCount: filteredStudents.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(filteredStudents[index]),
);
},
)
39. ListView.builder with Selection
Selection can be implemented by storing the selected index or selected item in application state.
int selectedIndex = -1;
ListView.builder(
itemCount: students.length,
itemBuilder: (context, index) {
return ListTile(
selected: selectedIndex == index,
title: Text(students[index]),
onTap: () {
setState(() {
selectedIndex = index;
});
},
);
},
)
40. ListView.builder and Keys
Keys help Flutter identify widgets when the order or identity of list items changes. For example, ValueKey can be useful when building dismissible or reorderable list items.
ListView.builder(
itemCount: products.length,
itemBuilder: (context, index) {
final product = products[index];
return ListTile(
key: ValueKey(product.name),
title: Text(product.name),
);
},
)
When the order of children can change and state needs to remain associated with the correct item, Flutter's API documentation notes that findChildIndexCallback may be needed to map an existing child to its new index. :contentReference[oaicite:8]{index=8}
41. Child Lifecycle
ListView.builder creates visible child subtrees lazily. When a child scrolls out of view, its element subtree, state, and render objects may be destroyed and recreated when it becomes visible again. For important application state, keep the source-of-truth data outside the individual list child or use an appropriate state-preservation strategy. :contentReference[oaicite:9]{index=9}
42. ListView.builder vs ListView
| Feature | ListView | ListView.builder |
| Data | Explicit widgets | Dynamic data |
| Child creation | Children are provided explicitly | Children are built on demand |
| Large lists | Less suitable | Suitable |
| Infinite lists | Not the typical approach | Suitable |
| itemBuilder | No | Yes |
| itemCount | No | Optional but recommended when known |
Flutter's documentation recommends the standard constructor for small lists and ListView.builder for large or potentially infinite lists. :contentReference[oaicite:10]{index=10}
43. ListView.builder vs ListView.separated
| Widget | Purpose |
ListView.builder | Builds dynamic list items on demand. |
ListView.separated | Builds dynamic list items with separators. |
44. ListView.builder vs GridView.builder
| Widget | Layout | Typical Usage |
ListView.builder | One-dimensional linear list | Contacts, messages, products, notifications |
GridView.builder | Two-dimensional grid | Product galleries, photo grids, dashboards |
45. ListView.builder Inside Column
When a ListView needs to occupy the remaining available space inside a Column, wrap it with Expanded.
Column(
children: [
const Text(
'Student List',
style: TextStyle(fontSize: 20),
),
Expanded(
child: ListView.builder(
itemCount: students.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(students[index]),
);
},
),
),
],
)
46. Common Mistakes
Mistake 1: Creating all widgets manually
For large dynamic data, use ListView.builder rather than manually creating a huge children list.
Mistake 2: Forgetting itemCount
ListView.builder(
itemCount: products.length,
itemBuilder: (context, index) {
return Text(products[index].name);
},
)
Mistake 3: Invalid index access
itemBuilder: (context, index) {
return Text(products[index].name);
}
Make sure the index is within the bounds of the data collection.
Mistake 4: Unnecessary shrinkWrap
Do not use shrinkWrap: true automatically. Use it when the layout actually requires content-based sizing.
Mistake 5: Starting expensive operations for every item
Keep network requests, complex calculations, and other expensive operations outside the item builder whenever possible.
Mistake 6: Forgetting to dispose ScrollController
@override
void dispose() {
controller.dispose();
super.dispose();
}
47. Performance Best Practices
- Use
ListView.builder for large or dynamic collections.
- Provide
itemCount when the number of items is known.
- Use
const widgets where possible.
- Avoid unnecessary
shrinkWrap.
- Use
itemExtent when all items have a known fixed extent.
- Use
prototypeItem when a representative fixed-size item is appropriate.
- Use
itemExtentBuilder when child extents can be determined from their indexes.
- Keep expensive data processing outside
itemBuilder.
- Use stable keys when item identity matters.
- Keep important application state in a source-of-truth model rather than relying on a list child remaining mounted.
- Dispose manually created controllers.
48. Complete Student List Example
import 'package:flutter/material.dart';
void main() {
runApp(const StudentApp());
}
class StudentApp extends StatelessWidget {
const StudentApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: const StudentPage(),
);
}
}
class StudentPage extends StatelessWidget {
const StudentPage({super.key});
final List
49. Practical Example – Product List
class Product {
final String name;
final double price;
Product({
required this.name,
required this.price,
});
}
class ProductPage extends StatelessWidget {
ProductPage({super.key});
final List products = [
Product(name: 'Laptop', price: 55000),
Product(name: 'Mobile Phone', price: 25000),
Product(name: 'Headphones', price: 3000),
Product(name: 'Keyboard', price: 1500),
Product(name: 'Mouse', price: 800),
];
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Products'),
),
body: ListView.builder(
itemCount: products.length,
itemBuilder: (context, index) {
final product = products[index];
return Card(
margin: const EdgeInsets.symmetric(
horizontal: 12,
vertical: 6,
),
child: ListTile(
leading: const CircleAvatar(
child: Icon(Icons.shopping_bag),
),
title: Text(product.name),
subtitle: Text(
'₹${product.price.toStringAsFixed(0)}',
),
onTap: () {
print(product.name);
},
),
);
},
),
);
}
}
50. Practical Example – Chat Messages
final List messages = [
'Hello!',
'How are you?',
'I am learning Flutter.',
'That is great!',
'Keep practicing.',
];
ListView.builder(
reverse: true,
padding: const EdgeInsets.all(12),
itemCount: messages.length,
itemBuilder: (context, index) {
return Align(
alignment: Alignment.centerRight,
child: Container(
margin: const EdgeInsets.only(bottom: 8),
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12),
color: Colors.blue,
),
child: Text(
messages[index],
style: const TextStyle(
color: Colors.white,
),
),
),
);
},
)
51. Practical Example – Notification List
final List
52. Practical Example – 10,000 Items
The following example demonstrates the main advantage of ListView.builder for a large collection.
final List items = List.generate(
10000,
(index) => 'Item $index',
);
ListView.builder(
itemCount: items.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(items[index]),
);
},
)
This follows the same pattern as Flutter's official long-list example. :contentReference[oaicite:11]{index=11}
53. ListView.builder Constructor – Important Properties
| Property | Purpose |
itemBuilder | Builds each list item. |
itemCount | Specifies the number of items. |
scrollDirection | Controls vertical or horizontal scrolling. |
reverse | Reverses the scroll direction. |
controller | Controls and observes scrolling. |
physics | Controls scroll behavior. |
shrinkWrap | Allows content-based sizing when required. |
padding | Adds space around the list. |
itemExtent | Specifies a fixed item extent. |
prototypeItem | Uses a representative widget to determine item extent. |
itemExtentBuilder | Calculates item extent based on index. |
findChildIndexCallback | Helps map an existing child to its new index when child order changes. |
addAutomaticKeepAlives | Controls automatic keep-alive behavior for children. |
addRepaintBoundaries | Controls automatic repaint boundaries for children. |
addSemanticIndexes | Controls automatic semantic indexes. |
These properties are part of the current Flutter ListView.builder API. :contentReference[oaicite:12]{index=12}
54. When Should You Use ListView.builder?
- When the number of items is dynamic.
- When displaying a large collection.
- When displaying API results.
- When displaying database records.
- When implementing infinite or very long lists.
- When items need to be created according to their indexes.
- When you want Flutter to create children on demand.
55. When Should You Use Normal ListView?
For a small number of fixed widgets, a normal ListView can be simpler.
ListView(
children: const [
ListTile(title: Text('Home')),
ListTile(title: Text('Profile')),
ListTile(title: Text('Settings')),
],
)
Flutter's documentation describes the regular constructor as appropriate for small lists and ListView.builder as appropriate for large or potentially infinite lists. :contentReference[oaicite:13]{index=13}
56. Practice Exercises
- Create a ListView.builder containing 20 student names.
- Create a product list containing product name, category, and price.
- Create a horizontal ListView.builder for product categories.
- Create a notification list using ListView.builder.
- Create a contact list with profile icons.
- Create a shopping cart with delete buttons.
- Implement swipe-to-delete using Dismissible.
- Create a chat interface using
reverse: true.
- Create a list with checkboxes for a task-management application.
- Create a search interface that filters ListView.builder items.
- Create a list that navigates to a detail page when an item is tapped.
- Create an API-based ListView with loading, error, empty, and success states.
- Create a 10,000-item list using
List.generate() and ListView.builder.
57. Quick Revision
- ListView.builder: Creates a scrollable list whose children are built on demand.
- itemBuilder: Builds the widget for each index.
- itemCount: Specifies the number of items when known.
- scrollDirection: Controls vertical or horizontal scrolling.
- reverse: Reverses the scrolling direction.
- controller: Provides programmatic scroll control.
- physics: Controls scrolling behavior.
- shrinkWrap: Allows the list to size itself around its contents when required.
- itemExtent: Specifies a fixed item extent.
- prototypeItem: Provides a representative item for determining extent.
- itemExtentBuilder: Calculates item extent based on the item index.
- findChildIndexCallback: Helps preserve child identity when item order changes.
58. Key Takeaways
ListView.builder is one of the most important Flutter widgets for displaying dynamic and large collections. Its itemBuilder callback creates widgets on demand, making it appropriate for long or potentially infinite lists. Providing itemCount when the total number of items is known helps Flutter estimate scroll extent. Properties such as scrollDirection, reverse, controller, physics, shrinkWrap, itemExtent, prototypeItem, and itemExtentBuilder provide control over scrolling and item layout. :contentReference[oaicite:14]{index=14}
59. Official Flutter Resources
60. Flutter Training Resources
For structured Flutter training covering Dart, Flutter widgets, layouts, scrolling, application development, and practical projects, visit:
JustAcademy Flutter Training Course
To register for a Flutter course demo:
Register for Flutter Course Demo